package threading;


class MyBlockingQueue {
    private int[] items = new int[1000];
    //约定 [head , tail ) 队列 的有效元素
    volatile private int head = 0;
    volatile private int tail = 0;
    volatile private int size = 0;

    //入队列
    synchronized public void put(int elem) throws InterruptedException {
        while  (size == items.length) {
            //队列满了 , 插入失败
            //return;
            this.wait();
        }
        //把新元素放到 tail 所在位置上
        items[tail] = elem;
        tail++;
        //万一 tail 达到末尾 , 就需要让 tail 从头再来
        if (tail == items.length) {
            tail = 0;
        }
        size++;
        this.notify();
    }
    //出队列
    synchronized public Integer take() throws InterruptedException {
        while(size == 0) {
            //return null;
            this.wait();
        }
        int value = items[head];
        head++;
        if (head == items.length) {
            head = 0;
        }
        size--;
        this.notify();
        return value;
    }
}
// 注意  上述两处代码的 wait 不可能同时阻塞 , 一个独立不可能即是空 又是满
public class ThreadDemo21 {
    public static void main(String[] args) {
        MyBlockingQueue queue = new MyBlockingQueue();
        //消费者
        Thread t1 = new Thread(() -> {
            while (true) {
                int value = 0;
                try {
                    value = queue.take();
                    System.out.println("消费 :" + value);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        });

        //生产者
        Thread t2 = new Thread(() -> {
            int value = 0;
            while (true) {

                try {
                    System.out.println("生产 : " + value);
                    queue.put(value);
                    Thread.sleep(1000);
                    value++;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t1.start();
        t2.start();

    }

}
